package com.zhuoyue.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.StrSubstitutor;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 数据帧拼接工具
 *
 * @author wjming
 */
public class CmdUtils {
    private static Pattern pattern = Pattern.compile("[0-9]*");
    private static String V$ = "$";

    private static final String CMD_2A = "2A";
    private static final String CMD_23 = "23";
    private static final Integer HEX_01 = 0x01;
    private static final int TWO = 2;
    private static final int FOUR = 4;
    private static final int EIGHT = 8;
    private static final int NINE = 9;

    /**
     * 计算指令长度
     *
     * @param body
     * @return
     */
    public static String getDateLength(String body) {
        return intToHexTwo(body.length() / 2);
    }

    /**
     * 计算长数据帧指令长度
     *
     * @param body
     * @return
     */
    public static String getDateLength2(String body) {
        int ff = 255;
        int length = body.length() / TWO;
        if (body.length() / TWO >= ff) {
            return "FF" + intToHexTwo(length - 255);
        } else {
            return intToHexTwo(body.length() / TWO);
        }

    }


    /**
     * 十进制转十六进制
     * 两位
     *
     * @param dec
     * @return
     */
    public static String intToHexTwo(int dec) {
        String hex = "";
        if (dec == 0) {
            hex = "00";
        } else {
            String str = Integer.toHexString(dec);
            if ((str.length() & HEX_01) == 1) {
                str = '0' + str;
            }
            hex = hex + str;
        }

        return hex.toUpperCase();
    }

    public static String intToHexFour(int dec) {
        String hex = "";
        if (dec == 0) {
            hex = "0000";
        } else {
            String str = Integer.toHexString(dec);
            if ((str.length() & HEX_01) == 1) {
                str = '0' + str;
            }
            hex = hex + str;
        }

        if (hex.length() == TWO) {
            hex = "00" + hex;
        }

        return hex.toUpperCase();
    }

    /**
     * 十进制转16禁止高位补零
     *
     * @param dec
     * @return
     */
    public static String intTo16(long dec) {
        String hex = "";
        if (dec == 0) {
            hex = "0000000000000000";
        } else {
//            String str = Long.toHexString(dec);
            hex = String.format("%016x", dec);
        }
        return hex.toUpperCase();
    }


    /**
     * 计算和校验值
     *
     * @param body
     * @return
     */
    public static String getCmdBodySum(String body) {
        int sum = 0;
        for (int i = 0; i < body.length(); i += TWO) {
            sum += Integer.parseInt(body.substring(i, i + 2), 16);
        }
        sum = sum & 0xff;
        String hexStr = Integer.toHexString(sum);
        if (hexStr.length() == 1) {
            hexStr = "0" + hexStr;
        }
        return hexStr.toUpperCase();
    }


    /**
     * 静音窗帘和校验计算
     */
    public static String getCmdBodySumCurtains(String body) {
        int sum = 0;
        for (int i = 0; i < body.length(); i += TWO) {
            sum += Integer.parseInt(body.substring(i, i + 2), 16);
        }
        sum = sum & 0xffff;
        sum = 0x2017 + sum;
        String hexStr = Integer.toHexString(sum);

        StringBuffer sb = new StringBuffer("");
        sb.append(hexStr.substring(2, 4));
        sb.append(hexStr.substring(0, 2));

        return sb.toString().toUpperCase();
    }


    /**
     * 得到十六进制数的静态方法
     *
     * @param decimalNumber 十进制数
     * @return 四位十六进制数字符串
     */
    public static String getHexString(int decimalNumber) {
        StringBuilder sb = new StringBuilder();
        //将十进制数转为十六进制数
        String hex = Integer.toHexString(decimalNumber);
        sb.append(hex);
        //加长到四位字符，用0补齐
        while (sb.length() < FOUR) {
            sb.insert(0, "0");
        }
        return sb.toString().toUpperCase();

    }

    /**
     * 得到十六进制数的静态方法
     *
     * @param decimalNumber 十进制数
     * @return 八位十六进制数字符串
     */
    public static String getHexEightString(int decimalNumber) {
        StringBuilder sb = new StringBuilder();
        //将十进制数转为十六进制数
        String hex = Integer.toHexString(decimalNumber);
        sb.append(hex);
        //加长到八位字符，用0补齐
        while (sb.length() < EIGHT) {
            sb.insert(0, "0");
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 四位数据帧高地位替换
     * 高位编程低位，低位变高位
     *
     * @param br
     * @return
     */
    public static String getHighPositionReplacement(String br) {
        String subSta = StringUtils.substring(br, 0, 2);
        String subEnd = StringUtils.substring(br, 2, 4);
        String sub = subEnd + subSta;
        return sub;
    }


    /**
     * 百分数转小数
     */
    public static Double getDoubleNum(String percentage) {
        //百分比转换为小数
        Double aDouble = null;
        String per0 = "0";
        String symbol = "%";
        String zeroSpot = "0.";
        if (StringUtils.startsWith(percentage, zeroSpot)) {
            aDouble = Double.valueOf(percentage);
        } else if (StringUtils.endsWith(percentage, symbol)) {
            percentage = percentage.replace(symbol, "");
            aDouble = Double.valueOf(percentage) / 100;
        } else if (!per0.equals(percentage) && pattern.matcher(percentage).matches()) {
            aDouble = Double.valueOf(Integer.valueOf(percentage)) / 100;
        } else {
            aDouble = 0.0;
        }
        return aDouble;
    }


    /**
     * @param: [content]
     * @return: int
     * @description: 十六进制转十进制
     */
    public static int covert16To10(String content) {
        int number = 0;
        int number10 = 10;
        String[] highLetter = {"A", "B", "C", "D", "E", "F"};
        Map<String, Integer> map = new HashMap<>(5);
        for (int i = 0; i <= NINE; i++) {
            map.put(i + "", i);
        }
        for (int j = 10; j < highLetter.length + number10; j++) {
            map.put(highLetter[j - 10], j);
        }
        String[] str = new String[content.length()];
        for (int i = 0; i < str.length; i++) {
            str[i] = content.substring(i, i + 1);
        }
        for (int i = 0; i < str.length; i++) {
            number += map.get(str[i]) * Math.pow(16, str.length - 1 - i);
        }
        return number;
    }

    public static String getCmd(Object cmdObject, String cmdMode) {
        Map<String, Object> cmdMap = JSONObject.parseObject(JSON.toJSONString(cmdObject));
        String cmd = new StrSubstitutor(cmdMap).replace(cmdMode);
        if (StringUtils.contains(cmd, V$)) {
            throw new ZyServerException(ErrorType.Service_Fail);
        }
        if (!StringUtils.startsWithIgnoreCase(cmd, CMD_2A) || !StringUtils.endsWithIgnoreCase(cmd, CMD_23)) {
            cmd = CMD_2A + getDateLength(cmd) + cmd + getCmdBodySum(cmd) + CMD_23;
        }
        return cmd;
    }

}
